package com.koi.classservice.controller;


import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.koi.classservice.Utils.CourseDataReverseParser;
import com.koi.classservice.domain.po.*;
import com.koi.classservice.domain.vo.CourseScheduleQueryVo;
import com.koi.classservice.domain.vo.CourseTestQueryVo;
import com.koi.classservice.handler.CourseExcelListener;
import com.koi.classservice.service.IBookClassService;
import com.koi.classservice.service.ICourseScheduleService;
import com.koi.classservice.service.ICourseService;
import com.koi.classservice.service.IReverseCourseScheduleService;
import com.koi.mccommon.Result;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author koi
 * @since 2025-03-29
 */
@RestController
@ApiModel(value = "教室预约")
@RequestMapping("/reversecourseschedule")
public class ReverseCourseScheduleController {

    @Autowired
    public IReverseCourseScheduleService courseScheduleService;

    @Autowired
    public ICourseService courseService;

    // 课程周次计算的起始日期
    private static final String START_DATE = "2025-02-24";
    // 日期格式化的模式
    private static final String DATE_FORMAT = "yyyy-MM-dd";
    // 中文星期几的数组，用于将数字星期转换为中文
    private static final String[] CHINESE_WEEKDAYS = {"一", "二", "三", "四", "五", "六", "日"};
    // 存储课程信息的 Excel 文件路径
    private static final String FILE_PATH = "class-service\\src\\main\\resources\\xlxFilm\\课表.xls";





    /**
     * 根据传入的查询参数查找空闲教室，并返回对应的课程信息列表
     * @param courseTestQueryVo 包含查询日期、起始节次和结束节次的查询参数对象
     * @return 封装了查询结果的 Result 对象，包含空闲教室对应的课程信息列表或错误信息
     */
    @PostMapping("/getReverseCourseSchedule")
    @ApiModelProperty(value = "根据时间查找空闲教室")
    public Result<List<Course>> getReverseCourseSchedule(@RequestBody(required = false) CourseTestQueryVo courseTestQueryVo) {
        try {

            LambdaQueryWrapper<Course> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Course::getDate, courseTestQueryVo.getDate());
            List<Course> courseList = courseService.list(queryWrapper);

            // 计算目标日期相对于起始日期的周数
            int weekNumber = calculateWeekNumber(courseTestQueryVo.getDate());
            // 获取目标日期对应的中文星期几
            String chineseWeekday = getChineseWeekday(courseTestQueryVo.getDate());

            // 判断是否是周末，如果是周末则返回错误信息
            if (isWeekend(chineseWeekday)) {
                return Result.error("周末没有可用教室");
            }

            // 从 Excel 文件中读取所有课程信息
            List<Course> allCourses = readCoursesFromExcel();
            // 根据查询参数和中文星期几构建节次查询条件
            String jie = buildJie(courseTestQueryVo, chineseWeekday);

            // 过滤出符合条件的空闲教室对应的课程信息
            List<Course> availableCourses = filterAvailableCourses(allCourses, weekNumber, jie, courseTestQueryVo);

            for (int i = 0; i < availableCourses.size(); i++) {
                Course course = availableCourses.get(i);
                //和courselist进行对比 然后删除
                for (int j = 0; j < courseList.size(); j++) {
                    Course course1 = courseList.get(j);
                    if (course1.getSession().equals(course.getSession())&&course.getClassroom().equals(course1.getClassroom())) {
                        availableCourses.remove(course);
                        break;
                    }
                }

            }




            // 对空闲教室对应的课程信息进行排序
            sortCourses(availableCourses);

            // 返回包含空闲教室课程信息列表的成功结果
            return Result.success(availableCourses);
        } catch (Exception e) {
            // 若出现异常，返回包含错误信息的结果
            return Result.error("查询空闲教室时出现错误：" + e.getMessage());
        }
    }

    /**
     * 计算目标日期相对于起始日期的周数
     * @param targetDateStr 目标日期的字符串表示
     * @return 目标日期相对于起始日期的周数
     */
    private int calculateWeekNumber(String targetDateStr) {
        // 创建日期格式化器，用于将日期字符串解析为 LocalDate 对象
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT);
        // 解析起始日期
        LocalDate startDate = LocalDate.parse(START_DATE, formatter);
        // 解析目标日期
        LocalDate targetDate = LocalDate.parse(targetDateStr, formatter);

        // 计算起始日期到目标日期的天数差
        long daysDifference = ChronoUnit.DAYS.between(startDate, targetDate);
        // 根据天数差计算周数
        return (int) (daysDifference / 7) + 1;
    }

    /**
     * 获取目标日期对应的中文星期几
     * @param targetDateStr 目标日期的字符串表示
     * @return 目标日期对应的中文星期几
     */
    private String getChineseWeekday(String targetDateStr) {
        // 创建日期格式化器
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT);
        // 解析目标日期
        LocalDate targetDate = LocalDate.parse(targetDateStr, formatter);
        // 获取目标日期是星期几（1 - 7）
        int dayOfWeek = targetDate.getDayOfWeek().getValue();
        // 根据数字星期从数组中获取对应的中文星期几
        return CHINESE_WEEKDAYS[dayOfWeek - 1];
    }

    /**
     * 判断传入的中文星期几是否为周末
     * @param chineseWeekday 中文星期几
     * @return 如果是周末返回 true，否则返回 false
     */
    private boolean isWeekend(String chineseWeekday) {
        return chineseWeekday.equals("六") || chineseWeekday.equals("日");
    }

    /**
     * 从 Excel 文件中读取所有课程信息
     * @return 包含所有课程信息的列表
     */
    private List<Course> readCoursesFromExcel() {
        // 创建 Excel 读取监听器
        CourseExcelListener listener = new CourseExcelListener();
        // 使用 EasyExcel 读取 Excel 文件，并将读取结果存储到监听器中
        EasyExcel.read(FILE_PATH, Course.class, listener).excelType(ExcelTypeEnum.XLS).sheet().doRead();
        // 从监听器中获取读取到的课程信息列表
        return listener.getCourses();
    }

    /**
     * 根据查询参数和中文星期几构建节次查询条件
     * @param courseTestQueryVo 查询参数对象
     * @param chineseWeekday 中文星期几
     * @return 构建好的节次查询条件
     */
    private String buildJie(CourseTestQueryVo courseTestQueryVo, String chineseWeekday) {
        // 判断是否没有传入起始节次和结束节次
        if (StringUtils.isEmpty(courseTestQueryVo.getClassStart()) && StringUtils.isEmpty(courseTestQueryVo.getClassEnd())) {
            // 若未传入，则查询条件仅为中文星期几
            return chineseWeekday;
        }
        // 若传入了起始节次和结束节次，则构建完整的节次查询条件
        return chineseWeekday + "[" + courseTestQueryVo.getClassStart() + "-" + courseTestQueryVo.getClassEnd() + "节]";
    }

    /**
     * 过滤出符合条件的空闲教室对应的课程信息
     * @param allCourses 所有课程信息列表
     * @param weekNumber 目标周数
     * @param jie 节次查询条件
     * @param courseTestQueryVo 查询参数对象
     * @return 符合条件的空闲教室对应的课程信息列表
     */
    private List<Course> filterAvailableCourses(List<Course> allCourses, int weekNumber, String jie, CourseTestQueryVo courseTestQueryVo) {
        // 构建教室与课程信息的映射关系
        Map<String, List<String>> classmap = buildClassMap(allCourses);
        // 用于存储空闲教室对应的课程信息，使用 Set 避免重复
        Set<Course> availableCourseSet = new HashSet<>();

        // 遍历教室与课程信息的映射
        for (Map.Entry<String, List<String>> entry : classmap.entrySet()) {
            // 获取教室名称
            String classroom = entry.getKey();
            // 获取该教室对应的课程信息列表
            List<String> courseInfoList = entry.getValue();

            // 遍历该教室的课程信息列表
            for (String courseInfo : courseInfoList) {
                // 解析课程信息
                CourseTest test = CourseDataReverseParser.parseCourses(courseInfo);
                // 判断该课程是否需要检查
                if (shouldCheckCourse(test, jie, courseTestQueryVo)) {
                    // 判断该课程在目标周是否被占用
                    if (!isCourseOccupied(test, weekNumber)) {
                        // 创建一个新的 Course 对象
                        Course c = new Course();
                        // 格式化教室名称并设置到 Course 对象中
                        c.setClassroom(formatClassroom(classroom));
                        // 设置课程的节次信息
                        c.setSession(test.getKeTime().substring(0, 7));
                        // 将该课程信息添加到空闲课程集合中
                        availableCourseSet.add(c);
                    }
                }
            }
        }

        // 将 Set 转换为 List 并返回
        return new ArrayList<>(availableCourseSet);
    }

    /**
     * 构建教室与课程信息的映射关系
     * @param allCourses 所有课程信息列表
     * @return 教室与课程信息的映射关系
     */
    private Map<String, List<String>> buildClassMap(List<Course> allCourses) {
        // 创建一个 HashMap 用于存储映射关系
        Map<String, List<String>> classmap = new HashMap<>();
        // 遍历所有课程信息
        for (Course course : allCourses) {
            // 获取教室名称
            String classroom = course.getClassroom();
            // 获取课程的周次信息
            String week = course.getWeek();
            // 获取课程的节次信息
            String session = course.getSession();
            // 组合周次和节次信息
            String courseInfo = week + "," + session;
            // 将课程信息添加到对应的教室映射中，如果教室不存在则创建新的列表
            classmap.computeIfAbsent(classroom, k -> new ArrayList<>()).add(courseInfo);
        }
        return classmap;
    }

    /**
     * 判断该课程是否需要检查
     * @param test 课程测试信息对象
     * @param jie 节次查询条件
     * @param courseTestQueryVo 查询参数对象
     * @return 如果需要检查返回 true，否则返回 false
     */
    private boolean shouldCheckCourse(CourseTest test, String jie, CourseTestQueryVo courseTestQueryVo) {
        // 判断是否没有传入起始节次或结束节次
        if (StringUtils.isEmpty(courseTestQueryVo.getClassStart()) || StringUtils.isEmpty(courseTestQueryVo.getClassEnd())) {
            // 若未传入，则只要课程的节次信息包含中文星期几就需要检查
            return test.getKeTime().contains(jie);
        }
        // 若传入了起始节次和结束节次，则需要检查课程的节次信息是否包含完整的查询条件
        return test.getKeTime().contains(jie);
    }

    /**
     * 判断该课程在目标周是否被占用
     * @param test 课程测试信息对象
     * @param weekNumber 目标周数
     * @return 如果被占用返回 true，否则返回 false
     */
    private boolean isCourseOccupied(CourseTest test, int weekNumber) {
        // 获取课程的周次列表
        List<Integer> weekList = test.getWeek();
        // 遍历周次列表
        for (Integer week : weekList) {
            // 判断是否有周次与目标周数相等
            if (week == weekNumber) {
                // 若相等则表示该课程在目标周被占用
                return true;
            }
        }
        // 若遍历完周次列表都没有找到与目标周数相等的周次，则表示该课程在目标周未被占用
        return false;
    }

    /**
     * 格式化教室名称
     * @param classroom 原始教室名称
     * @return 格式化后的教室名称
     */
    private String formatClassroom(String classroom) {
        // 按 "_" 分割教室名称
        String[] parts = classroom.split("_");
        // 组合分割后的部分
        return parts[0] + parts[1];
    }

    /**
     * 对课程信息列表进行排序，先按节次排序，再按教室排序
     * @param courses 课程信息列表
     */
    private void sortCourses(List<Course> courses) {
        // 使用 Comparator 对课程列表进行排序，先按节次排序，若节次相同则按教室名称排序
        courses.sort(Comparator.comparing(Course::getSession).thenComparing(Course::getClassroom));
    }



    //    @PostMapping("/getReverseCourseSchedule")
//    @ApiModelProperty(value = "根据时间查找空闲教室")
//    public Result<List<String>> getReverseCourseSchedule(
//            @RequestBody(required = false) CourseTestQueryVo courseTestQueryVo)
//    {
//
//        String startDateStr = "2025-02-24";
//        String targetDateStr = courseTestQueryVo.getDate();
//
//        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
//        LocalDate startDate = LocalDate.parse(startDateStr, formatter);
//        LocalDate targetDate = LocalDate.parse(targetDateStr, formatter);
//
//        // 计算从起始日期到目标日期的天数差
//        long daysDifference = ChronoUnit.DAYS.between(startDate, targetDate);
//
//        // 调整周数计算逻辑
//        int weekNumber = (int) (daysDifference / 7) + 1;
//
//        // 获取目标日期是星期几（1 代表星期一，7 代表星期日）
//        int dayOfWeek = targetDate.getDayOfWeek().getValue();
//
//        int target = weekNumber;
//        String[] chineseWeekdays = {"一", "二", "三", "四", "五", "六", "日"};
//        String chineseWeekday = chineseWeekdays[dayOfWeek - 1];
//        if (chineseWeekday.equals("六") || chineseWeekday.equals("日")) {
//            return Result.error("周末没有可用教室");
//        }
//
//        List<String> huifu = new ArrayList<>();
//        HashSet<String> huifu2 = new HashSet<>();
//
//        String filePath = "D:\\MyClub\\MyClub\\class-service\\src\\main\\resources\\xlxFilm\\课表.xls";
//        CourseExcelListener listener = new CourseExcelListener();
//        EasyExcel.read(filePath, Course.class, listener).sheet().doRead();
//        List<Course> courses = listener.getCourses();
//
//        String jie;
//        if (StringUtils.isEmpty(courseTestQueryVo.getClassStart() ) && StringUtils.isEmpty(courseTestQueryVo.getClassEnd())) {
//            // 如果没有提供节次信息，则查询所有节次
//            jie = chineseWeekday;
//        }
//        else {
//            jie = chineseWeekday + "[" + courseTestQueryVo.getClassStart() + "-" + courseTestQueryVo.getClassEnd() + "节]";
//        }
//
//        HashMap<String, List<String>> classmap = new HashMap<>();
//        for (Course course : courses) {
//            String classroom = course.getClassroom();
//            String week = course.getWeek();
//            String session = course.getSession();
//            String list = week + "," + session;
//            if (classmap.containsKey(classroom)) {
//                classmap.get(classroom).add(list);
//            } else {
//                List<String> list1 = new ArrayList<>();
//                list1.add(list);
//                classmap.put(classroom, list1);
//            }
//        }
//        // 拿到 map 里面的数据
//        for (String classroom : classmap.keySet()) {
//            List<String> list = classmap.get(classroom);
//            CourseTest test;
//            for (String s : list) {
//                test = CourseDataReverseParser.parseCourses(s);
//                if (courseTestQueryVo.getClassStart() == null || courseTestQueryVo.getClassEnd() == null) {
//                    // 如果查询所有节次，只检查星期几
//                    if (test.getKeTime().contains(chineseWeekday)) {
//                        int flag = 0;
//                        List<Integer> list1 = test.getWeek();
//                        for (Integer integer : list1) {
//                            if (integer == target) {
//                                flag = 1;
//                                break;
//                            }
//                        }
//                        if (flag == 0) {
//                            String[] s1 = classroom.split("_");
//                            huifu2.add(s1[0] + s1[1]);
//                        }
//                    }
//                } else {
//                    if (test.getKeTime().contains(jie)) {
//                        int flag = 0;
//                        List<Integer> list1 = test.getWeek();
//                        for (Integer integer : list1) {
//                            if (integer == target) {
//                                flag = 1;
//                                break;
//                            }
//                        }
//                        if (flag == 0) {
//                            String[] s1 = classroom.split("_");
//                            huifu2.add(s1[0] + s1[1]);
//                        }
//                    }
//                }
//            }
//        }
//        for (String s : huifu2) {
//            huifu.add(s);
//        }
//        return Result.success(huifu);
//    }







//    @PostMapping("/getReverseCourseSchedule")
//    @ApiModelProperty(value = "根据时间查找空闲教室")
//    public Result<List<Course>> getReverseCourseSchedule(
//            @RequestBody(required = false) CourseTestQueryVo courseTestQueryVo)
//    {
//
//        String startDateStr = "2025-02-24";
//        String targetDateStr = courseTestQueryVo.getDate();
//
//        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
//        LocalDate startDate = LocalDate.parse(startDateStr, formatter);
//        LocalDate targetDate = LocalDate.parse(targetDateStr, formatter);
//
//        // 计算从起始日期到目标日期的天数差
//        long daysDifference = ChronoUnit.DAYS.between(startDate, targetDate);
//
//        // 调整周数计算逻辑
//        int weekNumber = (int) (daysDifference / 7) + 1;
//
//        // 获取目标日期是星期几（1 代表星期一，7 代表星期日）
//        int dayOfWeek = targetDate.getDayOfWeek().getValue();
//
//        int target = weekNumber;
//        String[] chineseWeekdays = {"一", "二", "三", "四", "五", "六", "日"};
//        String chineseWeekday = chineseWeekdays[dayOfWeek - 1];
//        if (chineseWeekday.equals("六") || chineseWeekday.equals("日")) {
//            return Result.error("周末没有可用教室");
//        }
//
//        List<Course> huifu = new ArrayList<>();
//        HashSet<Course> huifu2 = new HashSet<>();
//
//        String filePath = "D:\\MyClub\\MyClub\\class-service\\src\\main\\resources\\xlxFilm\\课表.xls";
//        CourseExcelListener listener = new CourseExcelListener();
//        EasyExcel.read(filePath, Course.class, listener).sheet().doRead();
//        List<Course> courses = listener.getCourses();
//
//        String jie;
//        if (StringUtils.isEmpty(courseTestQueryVo.getClassStart() ) && StringUtils.isEmpty(courseTestQueryVo.getClassEnd())) {
//            // 如果没有提供节次信息，则查询所有节次
//            jie = chineseWeekday;
//        }
//        else {
//            jie = chineseWeekday + "[" + courseTestQueryVo.getClassStart() + "-" + courseTestQueryVo.getClassEnd() + "节]";
//        }
//
//        HashMap<String, List<String>> classmap = new HashMap<>();
//        for (Course course : courses) {
//            String classroom = course.getClassroom();
//            String week = course.getWeek();
//            String session = course.getSession();
//            String list = week + "," + session;
//            if (classmap.containsKey(classroom)) {
//                classmap.get(classroom).add(list);
//            } else {
//                List<String> list1 = new ArrayList<>();
//                list1.add(list);
//                classmap.put(classroom, list1);
//            }
//        }
//        // 拿到 map 里面的数据
//        for (String classroom : classmap.keySet()) {
//            List<String> list = classmap.get(classroom);
//            CourseTest test;
//            for (String s : list) {
//                test = CourseDataReverseParser.parseCourses(s);
//                if (courseTestQueryVo.getClassStart() == null || courseTestQueryVo.getClassEnd() == null) {
//                    // 如果查询所有节次，只检查星期几
//                    if (test.getKeTime().contains(chineseWeekday)) {
//                        int flag = 0;
//                        List<Integer> list1 = test.getWeek();
//                        for (Integer integer : list1) {
//                            if (integer == target) {
//                                flag = 1;
//                                break;
//                            }
//                        }
//                        if (flag == 0) {
//                            String[] s1 = classroom.split("_");
//                            Course c=new Course();
//                            c.setClassroom(s1[0]+s1[1]);
//                            c.setSession(test.getKeTime().substring(0,7));
//                            huifu2.add(c);
//                        }
//                    }
//                } else {
//                    if (test.getKeTime().contains(jie)) {
//                        int flag = 0;
//                        List<Integer> list1 = test.getWeek();
//                        for (Integer integer : list1) {
//                            if (integer == target) {
//                                flag = 1;
//                                break;
//                            }
//                        }
//                        if (flag == 0) {
//                            String[] s1 = classroom.split("_");
//                            Course c=new Course();
//                            c.setClassroom(s1[0]+s1[1]);
//                            c.setSession(test.getKeTime().substring(0,7));
//                            huifu2.add(c);
//                        }
//                    }
//                }
//            }
//        }
//        for (Course c : huifu2) {
//            huifu.add(c);
//        }
//        huifu.sort(new Comparator<Course>() {
//            @Override
//            public int compare(Course o1, Course o2) {
//                // 按照星期几排序
//                int weekCompare = o1.getSession().compareTo(o2.getSession());
//                if (weekCompare != 0) {
//                    return weekCompare;
//                }
//                // 再按照教室排序
//                return o1.getClassroom().compareTo(o2.getClassroom());
//            }
//        });
//
//        return Result.success(huifu);
//    }




}